#ifndef XGE_XTIMER_H_
#define XGE_XTIMER_H_
#include "xge_common_config.h"
#include "xassert.h"
#include "xstring.h"
#include "xsys_log.h"

// for linking to the Winmm.lib
#pragma comment(lib,"Winmm.lib")

namespace xge{
namespace xge_internal{

  // This timer is specifically used in the
  // message loop to retrieve the time difference
  // instead of getting the precise time or absolute time
  // using the timer accumulation to decide the task is 
  // time out or not .
  class Timer {
  public:
    // Since the timeGetTime ( without timeBeginPeriod and timeEndPeriod has only 15.9 ms precision )
    // we represent it as the threshold 
    // if the wanted precision is given 
    // we may use timeBeginPeriod and timeEndPeriod to adjust the
    // precision 
    static const size_t kMinMicrosecondPrecision = 16 ;
    // wrape a class as the tick_t
    class tick_t {
    public:
      tick_t() : tick_(size_t()) {}
      tick_t( size_t value ) : tick_(value) {}
      tick_t& operator = ( const tick_t& tick ) {
        tick_ = tick.tick_;
        return *this;
      }
      tick_t& operator = ( const size_t value ) {
        tick_ = value;
        return *this;
      }

      operator size_t() const {
        return (tick_);
      }

      tick_t( const tick_t& tick ) : tick_(tick.tick_){}
      tick_t operator + ( const tick_t& tick ) const {
        return tick_t( tick_ + tick.tick_ );
      }
      tick_t& operator +=( const tick_t& tick ) {
        return (*this) = (*this) + tick;
      }
      tick_t operator - ( const tick_t& tick ) const {
        return tick_t( tick_ - tick.tick_);
      }
      tick_t& operator -=( const tick_t& tick ) {
        return (*this) = (*this) - tick;
      }

    public:
      // To Second 
      float ToSecond() const {
        return (float)( (float)tick_ / kPerSecondTick );
      }
    private:
      size_t tick_;
      // This may change according to the internal implementation 
      static const float kPerSecondTick ;
    };
    // This timer will get the Now in the string
    // represent as below:
    // Fri Dec 16 17:13:03 2011
    static const String& Now() ;
    // This will internally begin counting time
    // If you want to use the timer in the loop you should always do like this:
    // XTimer timer;
    // 
    // timer.BeginTimerCounting();
    // 
    // while( true ) {
    //   float diff_time = timer.TimeDiff();
    //    // diff_time is the time difference 
    //    // now you know the time elapsed between last loop and this loop 
    //    ... 
    // }
    // 
    bool BeginTimerCounting( size_t high_resolution =kMinMicrosecondPrecision );
    // get the time different between two calling of this timer.TimeDiff()
    // listen , the first call of TimeDiff is not precise , since it will
    // always return zero . 
    tick_t TimeDiff() ;
    // the ctor
    Timer():last_call_timer_(0u),high_resolution_adjust_(kNoNeedToAdjust){}
    ~Timer();

  private:
    // the timer call last time
    tick_t last_call_timer_;
    // the timer precision adjust 
    // the initial non-adjust value is 0
    // which means if this value is set to kNoNeedToAdjust 
    // ok , no adjustment goes here 
    size_t high_resolution_adjust_ ; 
    // the time string catch
    static String kNowStr;
    static const size_t kNoNeedToAdjust = 0;
  };


}
}
#endif// XGE_XTIMER_H_